package top.yaofengqiao.springcloudsimple.auth.biz.domain.security.provider;

import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.LockedException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Component;
import top.yaofengqiao.springcloudsimple.auth.biz.domain.auth.model.valobj.Oauth2Type;
import top.yaofengqiao.springcloudsimple.auth.biz.domain.security.model.Oauth2AuthenticationToken;
import top.yaofengqiao.springcloudsimple.auth.biz.domain.security.model.UserInfo;
import top.yaofengqiao.springcloudsimple.common.constant.ResponseCode;
import top.yaofengqiao.springcloudsimple.common.util.AppException;

import javax.annotation.Resource;

/**
 * @author yfq
 * @date 2024/6/11 14:00
 * @description
 */
@Component
public class Oauth2AuthenticationProvider implements AuthenticationProvider {
    @Resource
    private UserDetailsService aliPayOauth2UserDetailService;
    @Resource
    private UserDetailsService weChatOauth2UserDetailService;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        Oauth2AuthenticationToken oauth2AuthenticationToken = (Oauth2AuthenticationToken) authentication;
        Oauth2Type oauth2Type = oauth2AuthenticationToken.getOauth2Type();
        String openid = oauth2AuthenticationToken.getCredentials().toString();

        UserDetails userDetails;
        switch (oauth2Type) {
            case ALIPAY:
                userDetails = aliPayOauth2UserDetailService.loadUserByUsername(openid);
                break;
            case WE_CHAT:
                userDetails = weChatOauth2UserDetailService.loadUserByUsername(openid);
                break;
            default:
                throw new AppException(ResponseCode.LOGIN_MODE_NO_SUPPORT);
        }

        // 账号不存在
        if (userDetails == null) throw new BadCredentialsException("Bad credentials");

        // 账号状态检查
        boolean accountNonLocked = userDetails.isAccountNonLocked();
        if (!accountNonLocked) throw new LockedException("User account is locked");

        oauth2AuthenticationToken.setUserInfo((UserInfo) userDetails);
        return authentication;
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return Oauth2AuthenticationToken.class.isAssignableFrom(authentication);
    }
}
